<?php
class Oa_Util_Db_Model extends OpModel
{
    protected $_table = NULL;
    protected $_dbClusterId = NULL;
    //Used with farm db
    protected $_objectId = NULL;
    
    private $_dbInstance = NULL;
    
    public $xcacheEnabled = FALSE;
    
    /**
     * 构造器
     * 
     * @param object $logger default NULL,日志记录对象
     * @param string $table default NULL, 表名，为NULL则不能使用基类提供的数据库操作方法
     * @param int $clusterId default NULL, 数据库cluster id
     * @param int $objectId default NULL, 对象id，用于分库选取用，单库不需要设置此参数
     */
    function __construct($logger = NULL, $table = NULL, $clusterId = NULL, $objectId = NULL)
    {
        parent::__construct($logger);
        
        $this->_table = $table;
        $this->_dbClusterId = $clusterId;
        $this->_objectId = $objectId;
        
        $this->xcacheEnabled = Oa_Util_Config::getConfig('xcache_enabled');
    }
    
    public function insert($insArr, $rawInsArr = NULL, $returnLastId = FALSE)
    {
        if ($this->_table === NULL) {
            return FALSE;
        }
        
        $db = $this->_getDbInstance();
        if (!$db) {
            return FALSE;
        }
        
        $sql = 'INSERT ' . $this->_table . getSqlInsert($insArr, $rawInsArr);
        $ret = $db->mod($sql);
        
        if ($ret === FALSE) {
            $this->log("[$sql] ".$db->getWriteErrorInfo());
            return FALSE;
        }
        
        if ($returnLastId) {
            return $db->getLastId();
        }
        
        return $ret;
    }
    
    public function insertReplace($insArr, $rawInsArr = NULL, $replaceArr = NULL, $rawReplaceArr = NULL)
    {
        if ($this->_table === NULL) {
            return FALSE;
        }
        
        $db = $this->_getDbInstance();
        if (!$db) {
            return FALSE;
        }
        
        $sql = 'INSERT ' . $this->_table
             . getSqlReplace($insArr, $rawInsArr, $replaceArr, $rawReplaceArr);
             
        $ret = $db->mod($sql);
        
        if ($ret === FALSE) {
            $this->log("[$sql] ".$db->getWriteErrorInfo());
            return FALSE;
        }
        
        return $ret;
    }
    
    public function update($conds, $uptArr, $rawUptArr = NULL, $otherConds = NULL)
    {
        if ($this->_table === NULL) {
            return FALSE;
        }
        
        $db = $this->_getDbInstance();
        if (!$db) {
            return FALSE;
        }
        
        $sql = 'UPDATE ' . $this->_table . getSqlUpdate($uptArr, $rawUptArr)
             . getSqlCond($conds, 0, 0, NULL, $otherConds);
        $ret = $db->mod($sql);
        
        if ($ret === FALSE) {
            $this->log("[$sql] ".$db->getWriteErrorInfo());
            return FALSE;
        }
        
        return $ret;
    }
    
    public function delete($conds, $otherConds = NULL)
    {
        if ($this->_table === NULL) {
            return FALSE;
        }
        
        $db  = $this->_getDbInstance();
        if (!$db) {
            return FALSE;
        }
        
        $sql = 'DELETE FROM ' . $this->_table 
             . getSqlCond($conds, 0, 0, NULL, $otherConds);
             
        $ret = $db->mod($sql);
        
        if ($ret === FALSE) {
            $this->log("[$sql] ".$db->getWriteErrorInfo());
            return FALSE;
        }
        
        return $ret;
    }
    
    public function select($conds, $start = 0, $count = 0, $sort = NULL, $otherConds = NULL, $selectFields = '*')
    {
        if ($this->_table === NULL) {
            return FALSE;
        }
        
        $db  = $this->_getDbInstance();
        if (!$db) {
            return FALSE;
        }
        
        $sql = "SELECT {$selectFields} FROM " . $this->_table
             . getSqlCond($conds, $start, $count, $sort, $otherConds);
        $res = NULL;
        if ($db->select($sql, $res) === FALSE) {
            $this->log("[$sql] ".$db->getReadErrorInfo());
            return FALSE;
        }
        
        return $res;
    }
    
    public function selectOne($conds, $otherConds = NULL, $sort = NULL, $selectFields = '*')
    {
        $res = $this->select($conds, 0, 1, $sort, $otherConds, $selectFields);
        if ($res === FALSE) {
            return FALSE;
        }
        if (empty($res)) {
            return NULL;
        }
        return $res[0];
    }
    
    public function selectCount($conds, $otherConds = NULL, $selectFields = 'COUNT(*)')
    {
        $res = $this->selectOne($conds, $otherConds, NULL, "{$selectFields} AS `total`");
        if ($res === FALSE) {
            return FALSE;
        }
        return intval($res['total']);
    }
    
   /**
    * Magic函数 
    * 用于实现 get_by_xxx/getByXxx方法 
    */
    public function __call ($name, $args)
    {
        if (strpos($name, 'get_by_') === 0) {
            $key = substr($name, 7);
            $value = $args[0];
            return $this->selectOne(array($key => $value));
        } elseif (strpos($name, 'getBy') === 0) {
            $key = strtolower(substr($name, 5));
            if ($key) {
                $conds = array($key => $args[0]);
                return $this->selectOne($conds);
            }
        }
        
    }
    
    protected function _getDbInstance()
    {
        if ($this->_dbInstance) {
            return $this->_dbInstance;    
        }
        
        if ($this->_dbClusterId !== NULL) {
            if ($this->_objectId !== NULL) {
                //It's farm db
                $this->_dbInstance = Oa_Util_Db_FarmDb::getInstanceByObjectId(
                    $this->_objectId,
                    $this->_dbClusterId
                );
            } else {
                $this->_dbInstance = Oa_Util_Db_GlobalDb::getInstance(
                    $this->_dbClusterId
                );
            }
            return $this->_dbInstance;
        }
        
        return NULL; 
    }
}